﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Collections.ObjectModel;
using MediaPlayer.Model;
using System.Windows.Input;
using System.IO;
using MediaPlayer.Interfaces;
using System.Windows.Controls;

namespace MediaPlayer.ViewModel
{
    public class VideoViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void NotifyPropertyChanged(String propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        // Permet de gérer les actions de la/les vues
        #region ICommand
        
        public ICommand cmdAddFilm { get; private set; }
        public ICommand cmdPlayFilm { get; private set; }
        public ICommand cmdPauseFilm { get; private set; }
        public ICommand cmdStopFilm { get; private set; }
        public ICommand cmdSavePlaylist { get; private set; }
        public ICommand cmdLoadPlaylist { get; private set; }
        
        public ICommand cmdVideoPrecedente { get; private set; }
        public ICommand cmdVideoSuivante { get; private set; }
        public ICommand cmdRalentir { get; private set; }
        public ICommand cmdAccelerer { get; private set; }

        public IMessageService MessageService { get; set; }

        #endregion


        // On instancie les ICommandes dans le constructeurs
        #region Constructor

        public VideoViewModel()
        {

            cmdAddFilm = new RelayCommand(AjouterFilm);
            cmdPlayFilm = new RelayCommand(PlayFilm);
            cmdPauseFilm = new RelayCommand(PauseFilm);
            cmdStopFilm = new RelayCommand(StopFilm);
            cmdSavePlaylist = new RelayCommand(SavePlaylist);
            cmdLoadPlaylist = new RelayCommand(LoadPlaylist);

            cmdVideoPrecedente = new RelayCommand(VideoPrecedente);
            cmdVideoSuivante = new RelayCommand(VideoSuivante);
            cmdRalentir = new RelayCommand(Ralentir);
            cmdAccelerer = new RelayCommand(Accelerer);
        }

        #endregion


        // Avec le MVVM, il ne faut pas utiliser les List<Quelquechoses>, il faut utiliser les ObservableCollection<Quelquechoses>
        #region Attributes

        private ObservableCollection<Video> _listVideo = new ObservableCollection<Video>();
        public ObservableCollection<Video> ListVideo
        {
            get
            {
                return _listVideo;
            }
            set
            {
                _listVideo = value;
            }
        }

        private Video _videoSelected = null;
        public Video VideoSelected
        {
            get
            {
                return _videoSelected;
            }
            set
            {
                _videoSelected = value;
            }
        }

        private string _pathVideoEnCours = string.Empty;
        public string PathVideoEnCours
        {
            get
            {
                return _pathVideoEnCours;
            }
            set
            {
                _pathVideoEnCours = value;
                NotifyPropertyChanged("PathVideoEnCours");
            }
        }

        public double _positionVideo = 0;
        public double PositionVideo
        {
            get
            {
                return _positionVideo;
            }
            set
            {
                _positionVideo = value;
                NotifyPropertyChanged("PositionVideo");
            }
        }


        public double _volumeVideo = 0.5;
        public double VolumeVideo
        {
            get
            {
                return _volumeVideo;
            }
            set
            {
                _volumeVideo = value;
                NotifyPropertyChanged("VolumeVideo");
            }
        }

        public MediaState _videoState = MediaState.Stop;
        public MediaState VideoState
        {
            get
            {
                return _videoState;
            }
            set
            {
                _videoState = value;
                NotifyPropertyChanged("VideoState");
            }
        }

        public double _vitesse = 1;
        public double Vitesse
        {
            get
            {
                return _vitesse;
            }
            set
            {
                _vitesse = value;
                NotifyPropertyChanged("Vitesse");
            }
        }

        #endregion


        // Méthodes appelées lorsqu'on actionne les commandes de la/les vues
        #region Commandes

        public void AjouterFilm()
        {
            if (MessageService == null)
                return;
            
            List<string> filenames = MessageService.OpenMultiFileDialog();
            if (filenames != null && filenames.Any())
            {
                foreach (string filename in filenames)
                {
                    Video newVideo = new Video(Path.GetFileName(filename), filename);
                    _listVideo.Add(newVideo);
                }
            }

            NotifyPropertyChanged("ListVideo");
        }

        public void PlayFilm()
        {
            if (VideoState == MediaState.Stop || VideoState == MediaState.Pause)
            {
                if (VideoSelected != null && PathVideoEnCours != VideoSelected.Source)
                    PathVideoEnCours = VideoSelected.Source;
                VideoState = MediaState.Play;
            }
        }

        public void PauseFilm()
        {
            if (VideoState == MediaState.Play)
                VideoState = MediaState.Pause;
        }

        public void StopFilm()
        {
            if (VideoState == MediaState.Play || VideoState == MediaState.Pause)
                VideoState = MediaState.Stop;
        }

        public void SavePlaylist()
        {
            if (MessageService == null)
                return;

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(ListVideo.GetType());

            string filename = MessageService.SaveFileDialog();
            if (!string.IsNullOrEmpty(filename))
            {
                using (FileStream file = File.OpenWrite(filename))
                {
                    serializer.Serialize(file, ListVideo);
                }
            }
        }

        public void LoadPlaylist()
        {
            if (MessageService == null)
                return;

            System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(ListVideo.GetType());
            
            string filename = MessageService.OpenFilesDialog();
            if (!string.IsNullOrEmpty(filename))
            {
                using (FileStream file = File.OpenRead(filename))
                {
                    try
                    {
                        _listVideo = (ObservableCollection<Video>)serializer.Deserialize(file);
                        NotifyPropertyChanged("ListVideo");
                    }
                    catch (Exception ex)
                    {
                        if (MessageService != null)
                            MessageService.ShowDialog("Erreur", ex.Message);
                    }
                }
            }
        }

         public void VideoPrecedente()
         {
             if (ListVideo != null && PathVideoEnCours != null)
             {
                 Video videoEnCours = ListVideo.FirstOrDefault(v=>v.Source == PathVideoEnCours);
                 if (videoEnCours != null)
                 {
                     int index = ListVideo.IndexOf(videoEnCours);
                     if (index > 0 && index < ListVideo.Count)
                     {
                         VideoState = MediaState.Stop;
                         VideoSelected = ListVideo[index - 1];
                         NotifyPropertyChanged("VideoSelected");
                         PlayFilm();
                     }
                 }
             }
         }

         public void VideoSuivante()
         {
             if (ListVideo != null && PathVideoEnCours != null)
             {
                 Video videoEnCours = ListVideo.FirstOrDefault(v => v.Source == PathVideoEnCours);
                 if (videoEnCours != null)
                 {
                     int index = ListVideo.IndexOf(videoEnCours);
                     if (index + 1 < ListVideo.Count)
                     {
                         VideoState = MediaState.Stop;
                         VideoSelected = ListVideo[index + 1];
                         NotifyPropertyChanged("VideoSelected");
                         PlayFilm();
                     }
                 }
             }
         }

         public void Ralentir()
         {
            Vitesse /= 2;
         }

         public void Accelerer()
         {
            Vitesse *= 2;
         }


        #endregion
    }
    

    /// <summary>
    /// 
    /// </summary>
    public class RelayCommand : ICommand
    {
        private readonly Action actionAExecuter;

        public RelayCommand(Action action)
        {
            actionAExecuter = action;
        }

        public bool CanExecute(object parameter)
        {
            if (CanExecuteChanged != null)
                return true;
            return false;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            actionAExecuter();
        }

    }
}

